package logic;

import java.util.HashSet;

import common.Fictionator;
import common.enums.AnswerEnum;
import common.interfaces.DBInterface;
import common.interfaces.PlayInterface;
import common.types.Pair;
import common.utils.CommonUtils;

public class PlayLogic implements PlayInterface {

	private DBInterface DBAccess;
	private int sessionID;
	private int lastCutIndexCounter;
	private int numberOfQuestion;
	private Pair<String, Integer> lastBestCut;
	private Pair<Integer, String> bestGuess;
	private HashSet<String> usedCutValues;
	private boolean isNoCut;
	private boolean isGameStarted = false;

	public PlayLogic() { }
	
	@Override
	public void startGame() throws Exception {
	    lastCutIndexCounter = 1;
        numberOfQuestion = 0;
        isNoCut = false;
		this.DBAccess = Fictionator.getInstance().getDBAccess();
		sessionID = DBAccess.getNewGameSessionID();	
		usedCutValues = new HashSet<String>();
		isGameStarted = true;
	}

	@Override
	public Pair<Integer, String> getNextQuestion() throws Exception {
		if (!isNoCut) {
			DBAccess.runAnalysis(sessionID);
		}
		int i = 0;
		do {
			lastBestCut = DBAccess.getBestCut(sessionID, lastCutIndexCounter + i);
			i++;
		} while (usedCutValues.contains(lastBestCut.getLeft()));
		String questionTemplate = DBAccess.getQuestionTemplate(lastBestCut.getRight());
		String question = CommonUtils.formatString(questionTemplate, lastBestCut.getLeft());
		numberOfQuestion++;
		return new Pair<Integer, String>(numberOfQuestion, question);
	}

	@Override
	public void submitAnswer(Pair<Integer, AnswerEnum> answer) throws Exception {
		if (answer.getLeft() != numberOfQuestion) {
			throw new Exception("GUI is out of sync");
		}
		if (answer.getRight().equals(AnswerEnum.DONT_KNOW)) {
			lastCutIndexCounter++;
			isNoCut = true;
		} else {
			lastCutIndexCounter = 1;
			isNoCut = false;
			DBAccess.makeCut(sessionID, lastBestCut.getRight(), answer.getRight());
		}
		usedCutValues.add(lastBestCut.getLeft());
	}
	
	@Override
	public boolean isGuessed() throws Exception {
		return numberOfQuestion >= 20 || DBAccess.isGuessReady(sessionID);
	}
	
	@Override
	public String getGuess() throws Exception {
		bestGuess = DBAccess.getBestGuess(sessionID);
		return bestGuess.getRight();
	}
	
	@Override
	public void submitActualGuess(Pair<Boolean, String> actualGuess) throws Exception {	
		DBAccess.submitActual(bestGuess.getLeft(), actualGuess.getLeft(), actualGuess.getRight());	
	}
	
	@Override
	public void finishGame() throws Exception {
		if (isGameStarted) {
			DBAccess.cleanGameSession(sessionID);
			isGameStarted = false;
		}
	}

}
